home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Personal Computer World 2009 February
/
PCWFEB09.iso
/
Software
/
Resources
/
Chat & Communication
/
PeerAware 1.03
/
PeerAware-Setup.exe
/
Html
/
scripts
/
vmlrenderer.js
< prev
Wrap
Text File
|
2008-09-07
|
68KB
|
2,434 lines
/* ***** BEGIN LICENSE BLOCK *****
This code has been relicensed under LGPL as permitted by original license.
Copyright Cumulate Draw Editor
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* ***** END LICENSE BLOCK ***** */
/**
* VML Renderer is responsible for all low level rendering operations associated with rendering for IE
*/
function VMLRenderer() {
this.base = AbstractRenderer;
}
VMLRenderer.prototype = new AbstractRenderer;
/**
*initialize the renderer
*@param editor element
**/
VMLRenderer.prototype.init = function(elem) {
this.container = elem;
this.container.style.overflow = 'hidden';
this.screenXDPI=screen.logicalXDPI / 72;
this.COORD_X=1000;
this.COORD_Y=1000;
// Add VML includes and namespace
elem.ownerDocument.namespaces.add("v", "urn:schemas-microsoft-com:vml");
elem.ownerDocument.namespaces.add("c", "urn:schemas-cumulatelabs-com:draw");
var style = elem.ownerDocument.createStyleSheet();
style.addRule('v\\:*', "behavior: url(#default#VML);");
this.minIndex=200;
this.maxIndex=200;
this.CONNECTOR_TAG='connector';
this.LINE_DELIMITER="\r\n";
this.EXTENSION='mmd';
this.TYPE="VML";
this.LONG_DASH="longdash";
this.SHORT_DASH="dash";
this.SOLID_DASH="solid";
}
/**
*get the id and bounds of the shape, if its a connector return the x,y,x2,y2 for it
**/
VMLRenderer.prototype.bounds = function(shape) {
if(!shape)return;
var rect = { x:0, y:0, width:0, height: 0,rotation:0,x2:0,y2:0,id:0,type:"",controlX:0,controlY:0,controlX2:0,controlY2:0 };
rect['id']=shape.getAttribute("id");
if(this.isConnector(shape))
{
rect['x']=this.pointToPixel(this.getConnectorFromX(shape));
rect['y']=this.pointToPixel(this.getConnectorFromY(shape));
rect['x2']=this.pointToPixel(this.getConnectorToX(shape));
rect['y2']=this.pointToPixel(this.getConnectorToY(shape));
rect['type']=this.getConnectorType(shape);
if(rect.type=='curve-line'){
var obj1=this.getControl1(shape);
var obj2=this.getControl2(shape);
rect['controlX']=obj1.x;
rect['controlY']=obj1.y;
rect['controlX2']=obj2.x;
rect['controlY2']=obj2.y;
}
}
else{
var rotation=shape.style.rotation;
rect['rotation']=shape.style.rotation;
if(!rect['rotation'])
rect['rotation']=0;
shape.style.rotation=0;
rect['x']=shape.style.left.split("px")[0];
rect['y']=shape.style.top.split("px")[0];
rect['width'] = (shape.style.width.split("px")[0]*1);
rect['height'] = (shape.style.height.split("px")[0]*1);
rect['left']=shape.offsetLeft;
rect['top']=shape.offsetTop;
shape.style.rotation=rotation;
}
return rect;
}
/**
* a utility function to convert points to pixels
**/
VMLRenderer.prototype.pointToPixel=function(point){
if(!point||point.length==0)return 0;
return (point*1)*this.screenXDPI;
}
/**
* a utitlity function to return an attribute in IE specific manner,assumes that element is not null
*@param element
*@param attribute name
**/
VMLRenderer.prototype.getAttribute=function(element,attribute){
return element.getAttribute(attribute);
}
/************************************SHAPE CREATION FUNCTIONS**************************/
/**
*load an xml shape for creation-
*TODO we will have to add some error handling later on
*/
VMLRenderer.prototype.loadShape=function(shapeID,retrieveTag){
var objValidXMLFile=this.loadXML("shapes/vml/"+shapeID+".xml");
var nodeList=objValidXMLFile.getElementsByTagName(retrieveTag);
if(retrieveTag){
var node=nodeList[0];
return node;
}
}
VMLRenderer.prototype.loadXML=function(path){
objValidXMLFile = new ActiveXObject("Microsoft.XMLDOM");
objValidXMLFile.async=false;
objValidXMLFile.load(path);
return objValidXMLFile;
}
/**
*load the orthogonal or line connector shape, the type (ortho or line) is determined by shape
*
**/
VMLRenderer.prototype.createLine=function(shape,lineColor,lineWidth,left,top,lineStyle){
doc=this.container.ownerDocument;
var vml=null;
var load=this.loadShape(shape,"c:connector");
var dummy = doc.createElement("div");
dummy.insertAdjacentHTML("AfterBegin", load.xml);
var parent = dummy.firstChild;
vml=this.getShapeSubject(parent);
if(shape=='line'){
vml.setAttribute("from",left+"px,"+top+"px");
vml.setAttribute("to",left+"px,"+top+"px");
}
else if(shape=='ortho-line'){
vml.points.value="0,0";
}
else{//this is a curve
vml.from="0,0";
vml.to="0,0";
vml.control1="1,1"
vml.control2="1,1";
}
vml.strokeweight=lineWidth;
vml.strokecolor=lineColor;
this.container.appendChild(parent);
vml.style.zIndex=this.maxIndex++;
this.setLineStyle(parent,lineStyle);
return parent;
}
/**
*indicate if the given shape is a connector
**/
VMLRenderer.prototype.isConnector=function(shape){
if(shape)
return (shape.tagName==this.CONNECTOR_TAG);
else return false;
}
/**
*create a grouped shape and set properties on the group instead of the shape
**/
VMLRenderer.prototype.create = function(shape, fillColor, lineColor, lineWidth, left, top, width, height,opacity,gradient,shadow) {
var rect;
doc=this.container.ownerDocument;
var vml=null;
var load=this.loadShape(shape,"v:group");
var dummy = doc.createElement("div");
dummy.insertAdjacentHTML("AfterBegin", load.xml);
vml = dummy.firstChild;
//first set the Z-index;
vml.style.zIndex=this.maxIndex++;
vml.style.rotation=0;
if (shape != 'line') {
vml.style.position = 'absolute';
vml.style.left = left;
vml.style.top = top;
vml.style.width = width;
vml.style.height = height;
}
if(opacity!=''){
this.setOpacity(vml,opacity);
}
//if(gradient!=''){
//this.setGradient(vml,gradient);
//}
if(shadow!=''){
this.setShadow(vml,shadow);
}
this.container.appendChild(vml);
return vml;
};
/**
* we had to introduce a hack for vml polylines, see savePolyLinePath for explanation
* @param shape
**/
VMLRenderer.prototype.copy=function(shape){
if(!shape)return null;
if(this.isConnector(shape)){
type=this.getConnectorType(shape);
if(type!='line'&&type!='curve-line'){
this.savePolyLinePath(shape);
}
}
return shape.outerHTML;
}
/**
* 06.01.2008 Jonny Rein: Added keepID, it is used to keep the same ID for the objects across
* different instances of a synced drawing.
**/
VMLRenderer.prototype.paste=function(shape,keepID){
if(!shape)return;
//get the outher html from clipboard and add it to div
var dummy = this.container.ownerDocument.createElement("div");
dummy.insertAdjacentHTML("AfterBegin", shape);
var node = dummy.firstChild;
var origId=node.id;
if (!keepID)
node.id='shape:' + createUUID();
if(!this.isConnector(node) && !keepID){
node.style.top=(node.style.top.split('px')[0]*1+10)+"px";
node.style.left=(node.style.left.split('px')[0]*1+10)+"px";
}
//now null any connections
var connectList=node.getElementsByTagName("connection");
var array=new Array();
for(var i=0;i<connectList.length;i++){
//if its a line emtpy it
if(node.tagName=='connector'){
connectList.item(i).setAttribute("shapeid","xx");
connectList.item(i).setAttribute("shapepoint","-1");
}
//if its a shape remove it!
else{
array[i]=connectList.item(i);
}
}
for(var i=0;i<array.length;i++){
array[i].removeNode(true);
}
//IE hack for lines and polylines where z-indexes have to be 0'ed out
if(this.isConnector(node)){
var type=this.getConnectorType(node);
var subject=this.getShapeSubject(node);
if(type=='line'||type=='curve-line'){
subject.style.zIndex=0;
}
else{
//additional hack for polylines where paths have to be 0'ed out
node.getElementsByTagName("polyline")[0].style.zIndex=0;
node.getElementsByTagName("polyline")[0].points="0,0";
}
}
//we have to do this in the renderer since IE messes around with path, so we can fix them
this.container.appendChild(node);
//now restore the polyline path
if(this.isConnector(node)&&type=='ortho-line'){
var points=node.getAttribute("polyline-path");
node.getElementsByTagName("polyline")[0].points.value=points;
}
this.bringToFront(node);
return node;
}
/**
* a pure unadulterated hack because IE does not mantain correspondence between,
* polyline.points.value and polyline.points.item(x).value
* so we basically save the value in an additional tag and use it when we have to do the paste or open
**/
VMLRenderer.prototype.savePolyLinePath=function(shape){
var polyline=shape.getElementsByTagName("polyline")[0];
var path="";
for (var i=0;i<polyline.points.length;i++){
path+=polyline.points.item(i).value+",";
}
shape.setAttribute("polyline-path",path);
}
/**
* this function is called to store the "correct" polyline paths before we refresh or save, see savePolylinePath for
* further explanation
**/
VMLRenderer.prototype.savePolyLinePaths=function(){
var nodes=this.getAllConnectors(this.container);
for (var i=0;i<nodes.length;i++){
if(nodes[i].getAttribute("type")=='ortho-line'){
this.savePolyLinePath(nodes[i]);
}
}
}
/**
*this method will return the actual subject of a shape, the subject could either be a path or line,polyline in case
of connectors, this assumes that the shape has only one subject, if a shape is comples with multiple sub-shapes
* see getAllSubshapes.
**/
VMLRenderer.prototype.getShapeSubject=function(shape){
if(!shape)return null;
if(this.isConnector(shape)){
var type=this.getConnectorType(shape);
if(type=='line')
return shape.getElementsByTagName('line')[0];
else if(type=='ortho-line')
return shape.getElementsByTagName('polyline')[0];
else
return shape.getElementsByTagName('curve')[0];
}
else{
var shapes=shape.getElementsByTagName("shape");
if(shapes.length>0){
return shapes[0];
}
//for backward compatibility only, these shapes are not used anymore!!!
else if(shape.getElementsByTagName("roundrect").length>0){
var shapes=shape.getElementsByTagName("roundrect");
if(shapes.length>0){
return shapes[0];
}
}
else if(shape.getElementsByTagName("rect").length>0){
var shapes=shape.getElementsByTagName("rect");
if(shapes.length>0){
return shapes[0];
}
}
else if(shape.getElementsByTagName("oval").length>0){
var shapes=shape.getElementsByTagName("oval");
if(shapes.length>0){
return shapes[0];
}
}
}
}
/**
* return all the subshapes for a given shape
* @param shape
* @return list of all subshapes
*/
VMLRenderer.prototype.getAllSubShapes=function(shape){
if(!shape)return null;
return shape.getElementsByTagName("shape");
}
/**************************************END SHAPE CREATION FUNCTIONS******************************/
/**************************************BEGIN SHAPE ATTRIBUTE GETTERS AND SETTERS*****************/
/**
*return the type of this connector
**/
VMLRenderer.prototype.getConnectorType=function(shape){
return shape.getAttribute("type");
}
/**
*get from x for a valid connector
**/
VMLRenderer.prototype.getConnectorFromX=function(shape){
var fromX=null;
var type=this.getConnectorType(shape);
if(type=='line'){
fromX=shape.getElementsByTagName("line")[0].from.x ;
}
else if (type=="ortho-line"){
var length=shape.getElementsByTagName("polyline")[0].points.length;
if(length==0){
return null;
}
fromX=shape.getElementsByTagName("polyline")[0].points.item(0).x ;
}
else if(type=="curve-line"){
fromX=this.getShapeSubject(shape).from.x;
}
return fromX;
}
/**
*get from y for a valid connector
**/
VMLRenderer.prototype.getConnectorFromY=function(shape){
var fromY=null;
var type=this.getConnectorType(shape);
if(type=='line'){
fromY=shape.getElementsByTagName("line")[0].from.y ;
}
else if (type=='ortho-line'){
var length=shape.getElementsByTagName("polyline")[0].points.length;
if(length==0){
return null;
}
fromY=shape.getElementsByTagName("polyline")[0].points.item(0).y ;
}
else if(type=="curve-line"){
fromY=this.getShapeSubject(shape).from.y;
}
return fromY;
}
/**
*get to x for a valid connector
**/
VMLRenderer.prototype.getConnectorToX=function(shape){
var toX=null;
var type=this.getConnectorType(shape);
if(type=='line'){
toX=shape.getElementsByTagName("line")[0].to.x ;
}
else if (type=='ortho-line'){
var length=shape.getElementsByTagName("polyline")[0].points.length;
if(length==0){
return null;
}
toX=shape.getElementsByTagName("polyline")[0].points.item(length-1).x ;
}
else if(type=="curve-line"){
toX=this.getShapeSubject(shape).to.x;
}
return toX;
}
/**
*get to y for a valid connector
**/
VMLRenderer.prototype.getConnectorToY=function(shape){
var toY=null;
var type=this.getConnectorType(shape);
if(type=='line'){
toY=shape.getElementsByTagName("line")[0].to.y ;
}
else if (type=='ortho-line'){
var length=shape.getElementsByTagName("polyline")[0].points.length;
if(length==0){
return null;
}
toY=shape.getElementsByTagName("polyline")[0].points.item(length-1).y ;
}
else if(type=="curve-line"){
toY=this.getShapeSubject(shape).to.y;
}
return toY;
}
/**
*set shape width
**/
VMLRenderer.prototype.setWidth=function(shape,width){
if(shape)
shape.style.width=width+"px";
}
/**
*set shape height
**/
VMLRenderer.prototype.setHeight=function(shape,height){
if(shape)
shape.style.height=height+"px";
}
/**
*set shape x (left)
**/
VMLRenderer.prototype.setX=function(shape,left){
if(shape)
shape.style.left=left+"px";
}
/**
*set shape Y(top)
**/
VMLRenderer.prototype.setY=function(shape,top){
if(shape)
shape.style.top=top+"px";
}
/**
*set shape rotation
**/
VMLRenderer.prototype.setRotation=function(shape,rotation){
rotation=rotation%360;
shape.style.rotation=rotation;
}
/**
*get all shape objects (not including connectors)!
**/
VMLRenderer.prototype.getAllShapes=function(doc){
var nodes=doc.getElementsByTagName("group");
var array=$A(nodes);
return array;
}
/**
*get all connectors (but not shapes)
**/
VMLRenderer.prototype.getAllConnectors=function(doc){
var nodes=doc.getElementsByTagName(this.CONNECTOR_TAG);
var array=$A(nodes);
return array;
}
/************************************END SHAPE ATTRIBUTE GETTERS AND SETTERS*********************************/
/************************************BEGIN Z-INDEX FUNCTIONS************************************************/
/**
update the min and max z-index based on index provided by shape, used during open
**/
VMLRenderer.prototype.updateZIndex=function(shape){
if(!shape)return;
if(this.isConnector(shape)){
shape=this.getShapeSubject(shape);
}
if(shape.style.zIndex<=this.minIndex){
this.minIndex=shape.style.zIndex;
this.minIndex--
}
if(shape.style.zIndex>=this.maxIndex){
this.maxIndex=shape.style.zIndex;
this.maxIndex++
}
}
/**
*send the shape to back
*update for polyline
**/
VMLRenderer.prototype.sendToBack=function(shape){
if(!shape){
return;
}
else{
this.setShapeZIndex(shape,this.minIndex--);
}
}
/**
*bring the shape to front
*
**/
VMLRenderer.prototype.bringToFront=function(shape){
if(!shape){
return;
}
else{
this.setShapeZIndex(shape,this.maxIndex++);
}
}
/**
* set the shape zindex and also bring the tracker to front or back, finally if
* this shape is a connector, bring any text to the front/back
*/
VMLRenderer.prototype.setShapeZIndex=function(shape,index){
var actualShape=shape;
if(this.isConnector(shape)){
actualShape=this.getShapeSubject(shape);
}
actualShape.style.zIndex=index;
var tracker = document.getElementById('tracker-group');
if(tracker)
tracker.style.zIndex=index;;
this.adjustConnectorTextZIndex(shape,index);
}
/**
* if a connector, adjust its text e.g bring it to front or back....
*/
VMLRenderer.prototype.adjustConnectorTextZIndex=function(shape,index){
//now check if this is a connector
if(this.isConnector(shape)){
var text=shape.getElementsByTagName('line');
for(var i=0;i<text.length;i++){
text[i].style.zIndex=index;
}
var bgShape=shape.getElementsByTagName("rect");
if(bgShape.length>0){
bgShape[0].style.zIndex=index;
}
}
}
/**
*remove the node in IE specfic manner
**/
VMLRenderer.prototype.remove = function(shape) {
if(shape)
shape.removeNode(true);
}
VMLRenderer.prototype.setCursor=function(shape,cursor){
shape.style.cursor=cursor;
}
/**
*move the shape, for line moves see moveLine
**/
VMLRenderer.prototype.move = function(shape, left, top) {
if(!shape){
return;
}
if (shape.tagName == 'line') {
shape.style.marginLeft = left;
shape.style.marginTop = top;
}
else {
shape.style.left = left;
shape.style.top = top;
}
};
/**
*respond to arrow keys for fine move
**/
VMLRenderer.prototype.fineMove = function(shape, move, isHorizontal) {
//todo fix for line!!!
if(!shape)return;
if (shape.tagName == 'line') {
shape.style.marginLeft = left;
shape.style.marginTop = top;
}
else {
if(isHorizontal){
var left=shape.style.left.split("px")[0];
left=(left*1)+move;
shape.style.left = left+"px";
}
else{
var top=shape.style.top.split("px")[0];
top=(top*1)+move;
shape.style.top = top+"px";
}
}
};
VMLRenderer.prototype.fineRotateSelection=function(shape,angle){
var rotation=shape.style.rotation;
if(!rotation)
rotation=0;
var rotation=rotation+angle;
rotation=rotation%360;
if(rotation<0){
rotation=360+rotation;
}
shape.style.rotation=rotation;
};
VMLRenderer.prototype.rotate=function(shape,rotation){
if(!rotation){
rotation=0;
}
rotation=rotation%360;
if(rotation<0){
rotation=360+rotation;
}
shape.style.rotation=rotation;
}
/**
*set the opacity
*/
VMLRenderer.prototype.setOpacity=function(shape,opacity){
//first check if this is a "complex" shape
var node=this.getShapeSubject(shape);
this.setFillAttribute(node,"opacity",opacity);
}
/**
*get the opacity
**/
VMLRenderer.prototype.getOpacity=function(shape){
var node=this.getShapeSubject(shape);
if(node){
var opacity=this.getFillAttribute(node,"opacity");
opacity=(opacity==null)?1.0:Math.round(opacity*10);
opacity=(opacity/10).toFixed(1);
return opacity;
}
else{
return null
}
}
/**
*get the gradient
**/
VMLRenderer.prototype.getGradient=function(shape){
var node=this.getShapeSubject(shape);
if(node){
var gradient=this.getFillAttribute(node,"type");
gradient=(gradient==null)?"solid":gradient;
return gradient;
}
else{
return null;
}
}
/**
*setFillcolor
**/
VMLRenderer.prototype.setFillColor=function(shape,fillColor){
//debugger;
//first check if this is a "complex" shape
var groups=shape.getElementsByTagName("v:group");
if(groups.length==0){
//this is a simple shape, so we will set its fill
var atts=new Array("fillcolor");
var vals=new Array(fillColor);
this.setShapeAttributes(shape,atts,vals);
}
else{
for(var i=0;i<groups.length;i++){
this.setFillColor(groups[i],fillColor);
}
}
}
/**
*get the fill color
*@param shape
**/
VMLRenderer.prototype.getFillColor=function(shape){
var node=this.getShapeSubject(shape);
if(node){
var fillColor=node.getAttribute("fillcolor");
if(fillColor) return fillColor.value;
else return "#ffffff";
}
else{
return "#ffffff";
}
}
/**
*get the line color
*@param shape
**/
VMLRenderer.prototype.getLineColor=function(shape){
var node=this.getShapeSubject(shape);
if(node){
var strokeColor=node.getAttribute("strokecolor");
if(strokeColor) return strokeColor.value;
else return "#ffffff";
}
else{
return "#ffffff";
}
}
/**
* get the line dash style
* @return one of -"solid", "short-dash","long-dash"
*/
VMLRenderer.prototype.getLineDashStyle=function(shape){
var subject=this.getShapeSubject(shape);
var stroke=subject.getElementsByTagName("stroke");
if(stroke.length==0)return 'solid';
var dashStyle=stroke[0].getAttribute("dashstyle");
if(!dashStyle||dashStyle.value==""||dashStyle.value==this.SOLID_DASH)
return 'solid';
else if(dashStyle.value.toLowerCase()==this.LONG_DASH)
return "long-dash";
else
return "short-dash";
}
/**
* set the line dash style, we will set this on all
*/
VMLRenderer.prototype.setLineDashStyle=function(shape,style){
if(style=="long-dash")style=this.LONG_DASH;
else if(style=="short-dash")style=this.SHORT_DASH;
else style=this.SOLID_DASH;
if(this.isConnector(shape)){
var subject=this.getShapeSubject(shape);
var stroke=subject.getElementsByTagName("stroke");
stroke[0].setAttribute("dashstyle",style)
}
else{
var subShapes=this.getAllSubShapes(shape)
for(var i=0;i<subShapes.length;i++){
var stroke=subShapes[i].getElementsByTagName("stroke");
if(!stroke||stroke.length==0){
stroke=this.createElement("stroke",this.VML_SVG_NAMESPACE);
subShapes[i].appendChild(stroke);
}
else{
stroke=stroke[0];
}
stroke.setAttribute("dashstyle",style)
}
}
}
/**
*get the stroke width of the shape
*@param shape
**/
VMLRenderer.prototype.getStrokeWidth=function(shape){
var node=this.getShapeSubject(shape);
if(node.getAttribute("strokeweight")!="undefined")
return (parseFloat(node.strokeweight) * (screen.logicalXDPI / 72)) + 'px';
else
return 0;
}
/**
*set the stroke width of the shape
*@param shape
**/
VMLRenderer.prototype.setStrokeWidth=function(shape,value){
if (value != '0px') {
shape.strokeweight = parseInt(value) + 'px';
attList=new Array("stroked","strokeweight");
attValues=new Array("true",parseInt(value)+'px');
this.setShapeAttributes(shape,attList,attValues);
}
else{
shape.stroked = 'false';
shape.strokeweight = 0 + 'px';
attList=new Array("stroked","strokeweight");
attValues=new Array("false",0+'px');
this.setShapeAttributes(shape,attList,attValues);
}
}
/**
*set gradient
*@param shape
**/
VMLRenderer.prototype.setGradient=function(shape,gradient){
var node=this.getShapeSubject(shape);
this.setFillAttribute(node,"type",gradient);
}
/**
*set the shape shadow
*@param shape
*@param shape value
**/
VMLRenderer.prototype.setShadow=function(shape,value){
//first check if this is a "complex" shape
var node=this.getShapeSubject(shape);
var shadowArray=node.getElementsByTagName("shadow");
var shadow=null;
if(!shadowArray||shadowArray.length==0){
shadow=this.container.ownerDocument.createElement("v:shadow");
node.appendChild(shadow);
}
else{
shadow=shadowArray[0];
}
shadow.on=value;
}
/**
*get shadow
*@param shape
**/
VMLRenderer.prototype.getShadow=function(shape){
var node=this.getShapeSubject(shape);
var shadowArray=node.getElementsByTagName("shadow");
if(!shadowArray||shadowArray.length==0){
return false;
}
return shadowArray[0].on;
}
/**
*set a value in the fill attribute
*@param node to set value in
*@param attribute name to be set e.g opacity
*@param value to be set
**/
VMLRenderer.prototype.setFillAttribute=function (node,att,value){
//debugger;
var fillArray=node.getElementsByTagName("fill");
var fill=null;
if(!fillArray||fillArray.length==0){
fill=this.container.ownerDocument.createElement("v:fill");
node.appendChild(fill);
}
else{
fill=fillArray[0];
}
var gradient=fill.type;
if(!gradient){
gradient="solid";
}
var atts=new Array("type",att);
var attValues=new Array(gradient,value);
setAttributes(fill,atts,attValues);
}
/**
* get a value in the fill attribute
**/
VMLRenderer.prototype.getFillAttribute=function(node,att){
var fillArray=node.getElementsByTagName("fill");
var fill=null;
if(!fillArray||fillArray.length==0){
return null;
}
else{
return fillArray[0].getAttribute(att);
}
}
/**
*resize shape
**/
VMLRenderer.prototype.resize = function(shape, fromX, fromY, toX, toY) {
var deltaX = toX - fromX;
var deltaY = toY - fromY;
if (this.isConnector(shape)) {
var type=this.getConnectorType(shape);
if(type=='line'){
var vml=shape.getElementsByTagName("line")[0];
vml.setAttribute('to', toX + 'px,' + toY + 'px');
}
else if(type=='ortho-line'){
this.drawOrthoLine(shape,fromX,fromY,toX,toY);
}
else if(type=='curve-line'){//this is a curve
this.drawCurveLine(shape,fromX,fromY,toX,toY,false);
}
}
else {
if (deltaX < 0) {
shape.style.left = toX + 'px';
shape.style.width = -deltaX + 'px';
}
else {
var width=0;
var newWidth=(width*1)+deltaX;
shape.style.width = (newWidth) + 'px';
}
if (deltaY < 0) {
shape.style.top = toY + 'px';
shape.style.height = -deltaY + 'px';
}
else {
var height=0;
var newHeight=(height*1)+deltaY;
shape.style.height = newHeight + 'px';
}
}
};
//a utility function to set attributes for all the child shapes within a group
//however we want to ignore all text elements
VMLRenderer.prototype.setShapeAttributes=function(group,attList,attValues){
var shape=this.getShapeSubject(group);
if(shape)
setAttributes(shape,attList,attValues);
}
/**a utility function to set attributes on an element
attlist and attvalues should have the same number of elements
**/
function setAttributes(element,attList,attValues){
for(var i=0;i<attList.length;i++){
element.setAttribute(attList[i],attValues[i]);
}
}
/**
*determine the appropriate handler for the command and respond.
*Zoom is provided to set up the correct sizing for font/lines etc
**/
VMLRenderer.prototype.editCommand = function(shape, cmd, value,zoom)
{
if (shape != null) {
if(cmd=='sendBack'){
this.sendToBack(shape);
}
else if(cmd=='bringFront'){
this.bringToFront(shape);
}
else if(cmd=='opacity'){
this.setOpacity(shape,value);
}
else if(cmd=='gradient'){
this.setGradient(shape,value);
}
else if(cmd=='shadow'){
this.setShadow(shape,value);
}
else if(cmd=='linestyle'){
this.setLineStyle(shape,value);
}
else if (cmd == 'fillcolor') {
if(this.isConnector(shape)){
return;
}
else if (value != '') {
shape.filled = 'true';
shape.fillcolor.value=value;
shape.fillcolor=value;
attList=new Array("filled","fillcolor");
attValues=new Array("true",value);
this.setShapeAttributes(shape,attList,attValues);
}
else {
shape.filled = 'false';
shape.setAttribute("fillcolor",value);
attList=new Array("filled","fillcolor");
attValues=new Array("true",value);
this.setShapeAttributes(shape,attList,attValues);
}
}
else if (cmd == 'linecolor') {
if (value != '') {
shape.stroked = 'true';
shape.strokecolor = value;
attList=new Array("stroked","strokecolor");
attValues=new Array("true",value);
this.setShapeAttributes(shape,attList,attValues);
}
else {
shape.stroked = 'false';
shape.strokecolor = '';
attList=new Array("stroked","strokecolor");
attValues=new Array("false",'');
this.setShapeAttributes(shape,attList,attValues);
}
}
else if (cmd == 'linewidth') {
this.setStrokeWidth(shape,value);
}
else if (cmd=='linedashstyle'){
this.setLineDashStyle(shape,value);
}
else if(cmd=='fontSize'||cmd=='fontFamily'||cmd=='bold'||cmd=='italic'||cmd=='fontColor'||cmd=='align'){
var font=new Object();
font.size='';
font.family='';
font.color='';
font.align='';
font.italics='';
font.bold='';
if(cmd=='fontSize'){
font.size=value;
this.setFont(shape,font,zoom);
}
else if(cmd=='fontFamily'){
font.family=value;
this.setFont(shape,font,zoom);
}
else if(cmd=='bold'){
var oldFont=this.getFont(shape);
if(oldFont.bold=='bold'){
font.bold='normal';
}
else{
font.bold='bold';
}
this.setFont(shape,font);
}
else if(cmd=='italic'){
//debugger;
var oldFont=this.getFont(shape);
if(oldFont.italics=='italic'){
font.italics='normal';
}
else{
font.italics='italic';
}
this.setFont(shape,font);
}
else if(cmd=='fontColor'){
font.color=value;
this.setFont(shape,font);
}
else if(cmd=='align'){
font.align=value;
this.setFont(shape,font);
}
}
}
}
VMLRenderer.prototype.queryCommand = function(shape, cmd)
{
if (shape != null) {
if (cmd == 'fillcolor') {
return this.getFillColor(shape);
}
else if (cmd == 'linecolor') {
return this.getLineColor(shape);
}
else if (cmd == 'linewidth') {
if (shape.stroked == 'false') {
return '';
}
else {
// VML always transforms the pixels to points, so we have to convert them back
return parseInt(this.getStrokeWidth(shape)) + 'px';
}
}
else if(cmd=='font'){
return this.getFont(shape);
}
else if(cmd=='linestyle'){
return this.getLineStyle(shape);
}
else if(cmd=='opacity'){
return this.getOpacity(shape);
}
else if(cmd=="gradient"){
return this.getGradient(shape);
}
else if(cmd=="shadow"){
return ""+this.getShadow(shape);
}
else if (cmd=='linedashstyle'){
return this.getLineDashStyle(shape);
}
}
}
/**
*create a handle shape, experimental, not used right now.
**/
VMLRenderer.prototype.getHandles=function(shape){
var handles=new Array();
if(!shape){
return handles;
}
var nodes=shape.getElementsByTagName("h");
if(nodes.length==0){
return handles;
}
//now get all the adjustments
var shapeNode=shape.getElementsByTagName("shape");
//if we have handles we must have adjustments
var adjLength=shapeNode[0].adj.length;
var adjs=new Array();
for(var i=0;i<adjLength;i++){
adjs[i]=shapeNode[0].adj.item(i);
}
//now lets create the handles
for(var i=0;i<nodes.length;i++){
var handle=this.container.ownerDocument.createElement("v:rect");
handle.coordsize="21600,21600";
handle.style.position="absolute";
handle.id="resize-right";
handle.style.width=30;
handle.style.position="absolute";
handle.style.height=30;
handle.setAttribute('filled', 'true');
handle.setAttribute('fillcolor', 'yellow');
var positionX=nodes[i].position.split(",")[0];
var positionY=nodes[i].position.split(",")[1];
if(positionX.indexOf("#")==0){
positionX=positionX.split("#")[1]*1;
handle.style.left=adjs[positionX]-20;
}
if(positionY.indexOf("#")==0){
positionY=positionY.split("#")[1];
handle.style.top=adjs[positionY]-20;
}
handles[handles.length]=handle;
}
return handles;
}
/**********************************begin line functions*******************/
/**
* move the "to" or "from" part of the line segment
*/
VMLRenderer.prototype.moveLine=function(shape,toX,toY, isFrom){
if(!this.isConnector(shape)){
return;
}
var type=this.getConnectorType(shape);
var vml=this.getShapeSubject(shape);
if(type=='line'||type=='curve-line'){
if(isFrom){
vml.setAttribute('from', toX + 'px,' + toY + 'px');
vml.from.x=toX/this.screenXDPI;
vml.from.y=toY/this.screenXDPI;
}
else{
vml.setAttribute('to', toX + 'px,' + toY + 'px');
vml.to.x=toX/this.screenXDPI;
vml.to.y=toY/this.screenXDPI;
}
}
else{
if(isFrom){
//debugger;
var length=vml.points.length;
var x=vml.points.item(length-1).x*this.screenXDPI;
var y=vml.points.item(length-1).y*this.screenXDPI
this.drawOrthoLine(shape,toX,toY,x,y);
}
else{
var x=vml.points.item(0).x*this.screenXDPI;
var y=vml.points.item(0).y*this.screenXDPI;
this.drawOrthoLine(shape,x,y,toX,toY);
}
}
}
/**
* the only difference between this method and move line is that this method converts pixels to points for polylines before
*setting them
**/
VMLRenderer.prototype.moveLinePoint=function(shape,toX,toY, isFrom){
if(!this.isConnector(shape)){
return;
}
var type=this.getConnectorType(shape);
var vml=this.getShapeSubject(shape);
if(type=='line'||type=='curve-line'){
if(isFrom){
vml.setAttribute('from', toX + 'pt,' + toY+'pt');
vml.from.x=toX;
vml.from.y=toY;
}
else{
vml.setAttribute('to', toX + 'pt,' + toY+'pt' );
vml.to.x=toX;
vml.to.y=toY;
}
}
else{
toX=toX*this.screenXDPI;
toY=toY*this.screenXDPI;
if(isFrom){
//debugger;
var length=vml.points.length;
var x=vml.points.item(length-1).x*this.screenXDPI;
var y=vml.points.item(length-1).y*this.screenXDPI;
this.drawOrthoLine(shape,toX,toY,x,y);
}
else{
var x=vml.points.item(0).x*this.screenXDPI;
var y=vml.points.item(0).y*this.screenXDPI;
this.drawOrthoLine(shape,x,y,toX,toY);
}
}
}
/*******************************************BEGIN CURVE CONNECTOR FUNCTIONS***********************************/
VMLRenderer.prototype.drawCurveLine=function(shape,fromX,fromY,toX,toY,resize){
var subject=this.getShapeSubject(shape);
subject.from=fromX+","+fromY;
subject.from.x=fromX/this.screenXDPI;
subject.from.y=fromY/this.screenXDPI;
subject.to=toX+","+toY;
subject.to.x=toX/this.screenXDPI;
subject.to.y=toY/this.screenXDPI;
if(!resize){
var x1=Math.abs(fromX-toX);
var y1=Math.abs(fromY-toY);
var cx1=(fromX<toX)?(fromX*1)+(x1*(1/4)):(fromX*1)-(x1*(1/4));
var cx2=(fromX<toX)?(toX*1)-(x1*(1/4)):(toX*1)+(x1*(1/4));
var cy1=(fromY<toY)?(fromY*1)+(y1*(1/4)):(fromY*1)-(y1*(1/4));
var cy2=(fromY<toY)?(toY*1)-(y1*(1/4)):(toY*1)+(y1*(1/4));
this.setControl1(shape,cx1,cy1);
this.setControl2(shape,cx2,cy2);
}
/********************************************END CURVE CONNECTOR FUNCTIONS*************************************/
/********************************************BEGIN GENERAL LINE FUNCTIONS***************************************/
}
/**
*get the location of control point 1
**/
VMLRenderer.prototype.getControl1=function(shape){
var subject=this.getShapeSubject(shape);
var obj=new Object();
obj.x=subject.control1.x*this.screenXDPI;
obj.y=subject.control1.y*this.screenXDPI;
return obj;
}
/**
*set the new location of control point 1
**/
VMLRenderer.prototype.setControl1=function(shape,cx1,cy1){
var subject=this.getShapeSubject(shape);
subject.control1=cx1+","+cy1;
subject.control1.x=cx1/this.screenXDPI;
subject.control1.y=cy1/this.screenXDPI;
}
/**
*get the location of control point 1
**/
VMLRenderer.prototype.getControl2=function(shape){
var subject=this.getShapeSubject(shape);
var obj=new Object();
obj.x=subject.control2.x*this.screenXDPI;
obj.y=subject.control2.y*this.screenXDPI;
return obj;
}
/**
*set the new location for control point 2
**/
VMLRenderer.prototype.setControl2=function(shape,cx1,cy1){
var subject=this.getShapeSubject(shape);
subject.control2=cx1+","+cy1;
subject.control2.x=cx1/this.screenXDPI;
subject.control2.y=cy1/this.screenXDPI;
}
/*******************************************BEGIN ORTHOGONAL CONNECTOR FUNCTIONS******************************/
/**
* get the segments of the orthogonal connector--get the central segment,
* @return {object} containing x,y,x2,y2
*/
VMLRenderer.prototype.getOrthoLineCenterSegment=function(shape){
//debugger;
var obj=new Object();
var points=this.getShapeSubject(shape).points;
//get the center point
var centerPoint=Math.round(points.length/2)-1;
var center=points.item(centerPoint);
var before=points.item(centerPoint-1);
var after=points.item(centerPoint+1);
var distanceA=((center.y-before.y)*(center.y-before.y))+((center.x-before.x)*(center.x-before.x));
var distanceB=((center.y-after.y)*(center.y-after.y))+((center.x-after.x)*(center.x-after.x));
var referencePoint=distanceA>distanceB?before:after;
if(distanceA>distanceB){
obj.x=this.pointToPixel(referencePoint.x);
obj.y=this.pointToPixel(referencePoint.y);
obj.x2=this.pointToPixel(center.x);
obj.y2=this.pointToPixel(center.y);
}
else{
obj.x2=this.pointToPixel(referencePoint.x);
obj.y2=this.pointToPixel(referencePoint.y);
obj.x=this.pointToPixel(center.x);
obj.y=this.pointToPixel(center.y);
}
return obj;
}
/*
*special method to draw orthogonal lines. first calculate the horizontal distance, then calculate the vertical distance,
* if horizontal> vertical, split horizontal in 1/2 and vice versa, set this in the shape
*/
VMLRenderer.prototype.drawOrthoLine= function(shape,fromX,fromY,toX,toY,resize){
var path=this.calculateOrthoLinePath(shape,fromX,fromY,toX,toY);
this.getShapeSubject(shape).points.value=path;
}
/*********************************************END ORTHOLINE FUNCTIONS*******************************/
/**
* get the current line style (arrow head style)
**/
VMLRenderer.prototype.getLineStyle=function(connector){
if(!this.isConnector(connector))return '';
var type=this.getConnectorType(connector);
var line=this.getShapeSubject(connector);
var stroke=line.getElementsByTagName('stroke')[0];
if(stroke.startarrow=='classic'&&stroke.endArrow=='classic'){
return 'arrow-both'
}
else if(stroke.startarrow=='classic'){
return 'arrow-from'
}
if(stroke.endArrow=='classic'){
return 'arrow-to'
}
else{
return 'none';
}
}
/**
* set the current line style (arrow head style)
**/
VMLRenderer.prototype.setLineStyle=function(connector,style){
if(!this.isConnector(connector))return;
var line=this.getShapeSubject(connector);
var stroke=line.getElementsByTagName('stroke')[0];
if(style=='arrow-from'||style=='arrow-both'){
stroke.startarrow='classic';
}
else{
stroke.startarrow='none';
}
if(style=='arrow-to'||style=='arrow-both'){
stroke.endarrow='classic';
}
else{
stroke.endarrow='none';
}
}
/**
* show the connection points for a shape
**/
VMLRenderer.prototype.showConnectionPoints=function(shape){
if(!shape)return;
//debugger;
var rect=this.bounds(shape);
var rotation=rect['rotation'];
if(!rotation)rotation=0;
this.remove($('active-shape-tracker'));
var doc=this.container.ownerDocument;
var group=doc.createElement("v:group");
group.style.left=shape.style.left;
group.style.top=shape.style.top;
group.style.width=shape.style.width;
group.style.height=shape.style.height;
group.style.position="ABSOLUTE";
group.style.rotation=rotation;
group.style.zIndex=(shape.style.zIndex*1)+1;
group.id='active-shape-tracker';
var width=10*(1000/(rect["width"]+50));
var height=10*(1000/(rect["height"]+50));
var nodeList=shape.getElementsByTagName("connection-point");
for(var i=0;i<nodeList.length;i++){
var node=nodeList.item(i);
var oval=doc.createElement("v:oval");
oval.filled="t";
oval.fillcolor="red";
oval.style.width="10px";
oval.style.height="10px";
oval.style.position="ABSOLUTE";
oval.style.width=width;
oval.style.height=height;
oval.style.left=(node.x-(width/2))+"px";
oval.style.top=(node.y-(height/2))+"px";
oval.coordsize="21600,21600";
group.appendChild(oval);
}
this.container.appendChild(group);
}
/**
*create a namespaced element
**/
VMLRenderer.prototype.createElement=function(elementTag,namespaceURI){
var element=null;
if(namespaceURI==this.VML_SVG_NAMESPACE)
elementTag="v:"+elementTag;
element= this.container.ownerDocument.createElement(elementTag);
if(namespaceURI=='CUMULATE_LABS'){
element.setAttribute("xmlns:c","urn:schemas-cumulatelabs-com:vml");
}
return element;
}
/*
*connectLine, first calculate if the line end matches a connection point
* if yes then add an entry to ensure that line and shape are connected
**/
VMLRenderer.prototype.connectLine=function(shape,connector,toOrFrom){
if(!connector)return;
//first disconnect the line
this.disconnectLineFromShape(connector,toOrFrom);
if(!shape)return;
//get the line coordinates in pixels
var screenxdpi=screen.logicalXDPI / 72;
var x=0;
var y=0;
var line=this.getShapeSubject(connector);
var type=this.getConnectorType(connector);
if(type=='line'||type=='curve-line'){
x=line.getAttribute(toOrFrom).x*this.screenXDPI;
y=line.getAttribute(toOrFrom).y*this.screenXDPI;
}
else{
if(toOrFrom=="from"){
x=line.points.item(0).x*this.screenXDPI;
y=line.points.item(0).y*this.screenXDPI;
}
else{
var length=connector.getElementsByTagName("polyline")[0].points.length;
if(length==0)return;
x=line.points.item(length-1).x*this.screenXDPI;
y=line.points.item(length-1).y*this.screenXDPI;
}
}
//now get the shape center
var left=shape.style.left.split('px')[0];
var top=shape.style.top.split('px')[0];
var width=shape.style.width.split('px')[0];
var height=shape.style.height.split('px')[0];
var centerX=(left*1)+(width/2);
var centerY=(top*1)+(height/2);
//get the rotation
var rotation=shape.style.rotation;
if(!rotation)rotation=0;
//get the shape coordinate size, hardcode for now
coordX=1000;
coordY=1000;
var connectionList=shape.getElementsByTagName("connection-point");
for(var i=0;i<connectionList.length;i++){
var node=connectionList.item(i);
//for each connection point get its(unrotated) pixel location
var conX=(left*1)+((node.x/coordX)*width);
var conY=(top*1)+((node.y/coordY)*height);
//now translate the center to the origin
conX=conX-centerX;
conY=conY-centerY;
//now rotate and translate back
finalX=((conX*Math.cos((Math.PI/180)*(rotation)))-(conY*Math.sin((Math.PI/180)*(rotation)))*1)+(centerX*1);
finalY=((conX*Math.sin((Math.PI/180)*(rotation)))+(conY*Math.cos((Math.PI/180)*(rotation)))*1)+(centerY*1);
if(x>(finalX-4)&&x<((finalX*1)+4)&&y>(finalY-4)&&y<((finalY*1)+4)){
this.connectLineToShape(shape,connector,toOrFrom,node,i);
var isFrom=(toOrFrom=="from")?true:false;
this.moveLineWithShape(shape);
$('help').innerHTML="Connected line to shape";
//no need to go on, we found our connection point
return;
}
}
}
/**
*show the line tracker
**/
VMLRenderer.prototype.showLineTracker=function(shape){
//debugger;
var doc=this.container.ownerDocument;
var vml=null;
var load=this.loadShape("tracker","c:line-tracker");
var dummy = doc.createElement("div");
dummy.insertAdjacentHTML("AfterBegin", load.xml);
var parent = dummy.firstChild;
parent.id="tracker-group";
this.updateLineTracker(shape,parent);
this.container.appendChild(parent);
return parent;
}
/**
*update the line tracker
**/
VMLRenderer.prototype.updateLineTracker=function(shape,parent){
var screenxdpi=screen.logicalXDPI / 72;
vml=parent.getElementsByTagName("oval")[0];
var type=this.getConnectorType(shape);
var line=this.getShapeSubject(shape);
var fromX,fromY=null;
if(type=='line'){
fromX=line.from.x;
fromY=line.from.y;
}
else if (type=='ortho-line'){
fromX=line.points.item(0).x;
fromY=line.points.item(0).y;
}
else if (type=='curve-line'){
fromX=line.from.x;
fromY=line.from.y;
var trackerLine=parent.getElementsByTagName("line")[0];
trackerLine.to=fromX+"pt,"+fromY+"pt";
}
vml.style.left=((parseFloat(fromX) * screenxdpi)-3) + 'px';
vml.style.top=((parseFloat(fromY) * screenxdpi)-3) + 'px';
vml.style.zIndex=this.maxIndex+1;
vml=parent.getElementsByTagName("oval")[1];
var toX,toY=null;
if(type=='line'){
toX=line.to.x;
toY=line.to.y;
}
else if (type=='ortho-line'){
var length=line.points.length;
if(length==0)return;
var toX=line.points.item(length-1).x;
var toY=line.points.item(length-1).y;
}
else if(type=='curve-line'){
toX=line.to.x;
toY=line.to.y;
var trackerLine=parent.getElementsByTagName("line")[1];
trackerLine.to=toX+"pt,"+toY+"pt";
}
vml.style.left=((parseFloat(toX) * screenxdpi)-3) + 'px';
vml.style.top=((parseFloat(toY) * screenxdpi)-3) + 'px';
vml.style.zIndex=this.maxIndex+1;
//now show the control points!
if(type=='curve-line'){
vml=parent.getElementsByTagName("oval")[2];
toX=line.control1.x;
toY=line.control1.y;
vml.style.left=((parseFloat(toX) * screenxdpi)-3) + 'px';
vml.style.top=((parseFloat(toY) * screenxdpi)-3) + 'px';
vml.style.zIndex=this.maxIndex+1;
vml.style.visibility="visible";
var trackerLine=parent.getElementsByTagName("line")[0];
trackerLine.from=toX+"pt,"+toY+"pt";
vml=parent.getElementsByTagName("oval")[3];
toX=line.control2.x;
toY=line.control2.y;
vml.style.left=((parseFloat(toX) * screenxdpi)-3) + 'px';
vml.style.top=((parseFloat(toY) * screenxdpi)-3) + 'px';
var trackerLine=parent.getElementsByTagName("line")[1];
trackerLine.from=toX+"pt,"+toY+"pt";
vml.style.zIndex=this.maxIndex+1;
vml.style.visibility="visible";
}
}
/*********************end line functions************************************************/
/**
*show tracker
**/
VMLRenderer.prototype.showTracker = function(shape) {
if(!shape)return;
if(shape.tagName=="connector"){
return this.showLineTracker(shape);
}
var box = this.bounds(shape);
var tracker = document.getElementById('tracker-group');
if (tracker) {
this.remove(tracker);
}
var group=this.container.ownerDocument.createElement("v:group");
group.id="tracker-group";
tracker = this.container.ownerDocument.createElement('v:shape');
tracker.id = 'tracker';
group.coordsize="1000,1000";
group.style.rotation=shape.style.rotation;
tracker.style.width=1000;
tracker.style.height=1000;
tracker.left='0';
tracker.top='0'
tracker.coordsize="1000,1000";
tracker.style.position="absolute";
//tracker.style.cursor='e-resize';
tracker.setAttribute('filled', 'false');
tracker.setAttribute('stroked', 'true');
tracker.setAttribute('strokecolor', '#aaaaaa');
tracker.setAttribute('strokeweight', '2px');
tracker.setAttribute("path","m0,0 l 1000,0,1000,1000,0,1000,0,0 e");
//var stroke=this.container.ownerDocument.createElement("v:stroke");
//stroke.setAttribute('dashstyle','DashDot');
//tracker.appendChild(stroke);
group.appendChild(tracker);
var width=10*(1000/(box["width"]+50));
var height=10*(1000/(box["height"]+50));
//now add the right resize
var rightstretch=this.container.ownerDocument.createElement("v:rect");
rightstretch.coordsize="21600,21600";
rightstretch.style.position="absolute";
//<v:rect id="resize-right" style="LEFT:950;WIDTH=100;POSITION:relative;top=400;height=100" filled='t' fillcolor="blue"/>
rightstretch.id="resize-right";
rightstretch.style.left=1000-(width/2);
rightstretch.style.width=width;
rightstretch.style.position="absolute";
rightstretch.style.top=500-(height/2);
rightstretch.style.height=height
rightstretch.setAttribute('filled', 'true');
rightstretch.setAttribute('fillcolor', '#cccccc');
group.appendChild(rightstretch);
var leftstretch=this.container.ownerDocument.createElement("v:rect");
leftstretch.coordsize="21600,21600";
leftstretch.style.position="absolute";
//<v:rect id="resize-right" style="LEFT:950;WIDTH=100;POSITION:relative;top=400;height=100" filled='t' fillcolor="blue"/>
leftstretch.id="resize-left";
leftstretch.style.left=-(width/2);
leftstretch.style.width=width;
leftstretch.style.position="absolute";
leftstretch.style.top=500-(height/2);
leftstretch.style.height=height;
leftstretch.setAttribute('filled', 'true');
leftstretch.setAttribute('fillcolor', '#cccccc');
group.appendChild(leftstretch);
var bottomstretch=this.container.ownerDocument.createElement("v:rect");
bottomstretch.coordsize="21600,21600";
bottomstretch.style.position="absolute";
bottomstretch.id="resize-bottom";
bottomstretch.style.left=500-width/2;
bottomstretch.style.width=width;
bottomstretch.style.position="absolute";
bottomstretch.style.top=1000-height/2;
bottomstretch.style.height=height;
bottomstretch.setAttribute('filled', 'true');
bottomstretch.setAttribute('fillcolor', '#cccccc');
group.appendChild(bottomstretch);
var topstretch=this.container.ownerDocument.createElement("v:rect");
topstretch.coordsize="21600,21600";
topstretch.style.position="absolute";
topstretch.id="resize-top";
topstretch.style.left=500-width/2;
topstretch.style.width=width
topstretch.style.position="absolute";
topstretch.style.top=-height/2;
topstretch.style.height=height;
topstretch.setAttribute('filled', 'true');
topstretch.setAttribute('fillcolor', '#cccccc');
group.appendChild(topstretch);
//<v:oval id="tracker-oval"
//fillcolor="blue"
//style="position:relative;top:-150;left:450;width:100;height:50;cursor:move">
//</v:oval>
var rotate=this.container.ownerDocument.createElement("v:oval");
rotate.id="tracker-rotate";
rotate.style.position="absolute";
rotate.style.top=-40*(1000/(box["height"]+30)) ;
var rotateWidth=10*(1000/(box["width"]+50));
rotate.style.width=rotateWidth;
rotate.style.left=500-(rotateWidth/2);
rotate.style.height=10*(1000/(box["height"]+50));
rotate.style.cursor='move';
rotate.setAttribute("filled",'true');
rotate.setAttribute("fillcolor",'#cccccc');
//todo create a line that goes to the center of the bounding box from the oval
//we will not do rotation rigt now, the browser does not seem to be able to handle it too well
group.appendChild(rotate);
var handles=this.getHandles(shape);
for (var i=0;i<handles.length;i++){
handles[i].id="tracker-handle:"+i;
group.appendChild(handles[i]);
}
//debugger;
group.style.left = box.x - 5;
group.style.top = box.y - 5;
group.style.width = (box["width"]*1) + 10;
group.style.height = (box["height"]*1) + 10;
group.style.position="absolute";
group.style.zIndex=shape.style.zIndex;
group.style.zoom=shape.style.zoom;
this.container.appendChild(group);
return group;
}
/**
*update the tracker
*@param the shape
**/
VMLRenderer.prototype.updateTracker = function(shape) {
var box = this.bounds(shape);
var tracker = document.getElementById('tracker-group');
if (tracker) {
if(shape.tagName=="connector"){
return this.updateLineTracker(shape,tracker);
}
tracker.style.left = box.x - 5;
tracker.style.top = box.y - 5;
tracker.style.width = (box["width"]*1) + 10;
tracker.style.height = (box["height"]*1) + 10;
tracker.style.rotation=box.rotation;
tracker.style.zIndex=shape.style.zIndex;
var rotate= document.getElementById('tracker-rotate');
rotate.style.top=-40*(1000/(box["height"]+30)) ;
var width=10*(1000/(box["width"]+50));
var height=10*(1000/(box["height"]+50));
rotate.style.width=width;
rotate.style.left=500-(width/2);
rotate.style.height=height;
var leftstretch= document.getElementById('resize-left');
leftstretch.style.left=-(width/2);
leftstretch.style.width=width;
leftstretch.style.top=500-(height/2);
leftstretch.style.height=height;
var rightstretch= document.getElementById('resize-right');
rightstretch.style.left=1000-(width/2);
rightstretch.style.width=width;
rightstretch.style.top=500-(height/2);
rightstretch.style.height=height
var topstretch= document.getElementById('resize-top');
topstretch.style.left=500-width/2;
topstretch.style.width=width
topstretch.style.top=-height/2;
topstretch.style.height=height;
var bottomstretch= document.getElementById('resize-bottom');
bottomstretch.style.left=500-width/2;
bottomstretch.style.width=width;
bottomstretch.style.position="absolute";
bottomstretch.style.top=1000-height/2;
bottomstretch.style.height=height;
}
else{
this.showTracker(shape);
}
}
VMLRenderer.prototype.getMarkup = function() {
return this.container.innerHTML;
}
/**incase of vm the selection source comes back as shape which resides in group/shape,
**in order to return group we need to climb 1 level
**/
VMLRenderer.prototype.getShapeFromEventSource=function(source){
if(source)return source.parentNode;
}
/**********************************************begin text rendering algorithms****************************************/
/**
* set the dimensions of the background shape for the connector text
* todo, fix visibility here...
*/
VMLRenderer.prototype.handleConnectorTextBackgroundPositioning=function(shape,rect,text){
var bgShape=this.getConnectorBackgroundShape(shape);
shape.appendChild(bgShape);
if(text&&trim(text).length>0){
this.setX(bgShape,rect.x);
this.setY(bgShape,rect.y);
this.setWidth(bgShape,rect.width);
this.setHeight(bgShape,rect.height);
}
else{
this.hideConnectorBackground(bgShape);
}
}
/**
* hide the connector background, this comes handy when we want to clear the connector text (during moves, resize etc)
* or when the text is empty
* @param background shape for the connector
*/
VMLRenderer.prototype.hideConnectorBackground=function(bgShape){
if(bgShape){
this.setX(bgShape,0);
this.setY(bgShape,0);
this.setWidth(bgShape,0);
this.setHeight(bgShape,0);
}
}
/**
* handle connector text line positioning
* this method will set line positioning for text rendered within connectors
*/
VMLRenderer.prototype.handleConnectorTextLinePositioning=function(height,width,x,y,center,fontSize,lines,shapeFont,shape){
var centerY=(y*1)+(height*1)/2;
var zIndex=this.getShapeSubject(shape).style.zIndex;
var shapeArray=new Array();
for (var i=center;i>0;i--){
var lineTopMargin=(centerY)+((fontSize*1.1)*(i-center));
//lineTopMargin=(lineTopMargin*1)+((fontSize)/4);
shapeArray[shapeArray.length]=this.createTextShape(lines[i-1],true,0,lineTopMargin,(x*1),(x)+(width*1),shapeFont,zIndex,shape);
}
for (var i=center;i<lines.length;i++){
var lineTopMargin=(centerY)+((fontSize*1.1)*(i+1-center));
//lineTopMargin=(lineTopMargin*1)+((fontSize)/4);
shapeArray[shapeArray.length]=this.createTextShape(lines[i],true,0,lineTopMargin,(x*1),(x)+(width*1),shapeFont,zIndex,shape);
}
return shapeArray;
}
/**
*create the text elements and handle text positioning
**/
VMLRenderer.prototype.handleTextLinePositioning=function(height,width,x,y,center,fontSize,lines,shapeFont,shape){
//if this shape has text bounds, we want to use that for height
var textBounds=shape.getElementsByTagName("text-bound");
var topMarginBegin=500;
var leftMarginBegin=10;
var rightMarginEnd=1000;
if(textBounds.length>0){
height=this.bounds(shape).height;
var textb=textBounds[0];
var x1=this.getAttribute(textb,"fromX");
leftMarginBegin=(leftMarginBegin*1)+(x1*1);
var x2=this.getAttribute(textb,"toX");
rightMarginEnd=x2-x1;
var y1=this.getAttribute(textb,"fromY");
var y2=this.getAttribute(textb,"toY");
topMarginBegin=(y1*1)+((y2-y1)/2);
}
var lineHeight=100;
//debugger;
if(height<=60&&height>=25){
lineHeight=((25/(height)+1)*0.9)*(60+(10*(fontSize-10)));
}
else if(height>60){
//if x>100 (25/(x-100))(1/2)*(50+(10*(fontsize-10)))
lineHeight=((25/((height)+1))*2.4)*(60+(10*(fontSize-10)));
}
else if (height<=25){
//debugger;
lineHeight=((25/(height)+1)*1.3)*(60+(10*(fontSize-10)));
}
var shapeArray=new Array();
for (var i=center;i>0;i--){
var lineTopMargin=(topMarginBegin)+((lineHeight+10)*(i-center))+((fontSize-10));
var lineHeightMargin=(i-center)*lineHeight;
shapeArray[shapeArray.length]=this.createTextShape(lines[i-1],true,lineTopMargin,lineHeightMargin,leftMarginBegin,(rightMarginEnd-10),shapeFont,null,shape);
}
for (var i=center;i<lines.length;i++){
var lineTopMargin=(topMarginBegin)+((lineHeight+10)*(i+1-center))+((fontSize-10));
var lineHeightMargin=(i+1-center)*lineHeight;
shapeArray[shapeArray.length]=this.createTextShape(lines[i],true,lineTopMargin,lineHeightMargin,leftMarginBegin,(rightMarginEnd-10),shapeFont,null,shape);
}
return shapeArray;
}
/**
* a utility function to create a text set, sometimes we may need to create a dummy text set (see setShapeText)in which case
* we need to pass the shape.id as the type in the line object and texpathok=false
*/
VMLRenderer.prototype.createTextShape
=function(line,textpathok,lineTopMargin,lineHeightMargin,start,end,shapeFont,zIndex,doc){
var doc=this.container.ownerDocument;
var shape=null;
var path=null;
var textPath=null;
if(!textpathok){
textPath=$("text:template"+line.type);
}
if(textpathok||!textPath){
shape=doc.createElement("v:line");
shape.id="text:"+line.type;
//shape.style.left=start+"px";
shape.style.position="absolute";
shape.style.height=50+"px";
shape.style.top=lineTopMargin+"px";
shape.from=start+","+lineHeightMargin;
shape.to=end+","+lineHeightMargin;
shape.filled=textpathok;
shape.fillcolor=shapeFont.color;
shape.stroked=false;//textpathok;
shape.strokecolor=shapeFont.color;
if(zIndex){
shape.style.zIndex=zIndex;
}
path=doc.createElement("v:path");
path.textpathok=textpathok;
shape.appendChild(path);
textPath=doc.createElement("v:textpath");
if(!textpathok){
textPath.id="text:template"+line.type;
}
shape.appendChild(textPath);
}
else{
shape=textPath.parentElement;
path=shape.getElementsByTagName("path")[0];
}
textPath.on=textpathok;
textPath.style.fontSize=shapeFont.size;
textPath.style.fontWeight=shapeFont.bold;
textPath.style.fontFamily=shapeFont.family;
shape.style.fontFamily=shapeFont.family;
path.style.fontFamily=shapeFont.family;
textPath.style.fontStyle=shapeFont.italics;
textPath.string=line.text;
textPath.style.cssText=textPath.style.cssText+";v-text-align:"+shapeFont.align+";";
return shape;
}
/**
*this method should be called only after getShapeText has been called by the editor
*to save the text
*/
VMLRenderer.prototype.clearShapeText=function(shape){
var nodes=shape.getElementsByTagName("line");
var nodeArray=$A(nodes);
var i=0;
if(this.isConnector(shape)&&this.getConnectorType(shape)=='line'){
i=1;
}
for(i;i<nodeArray.length;i++){
var node=nodeArray[i];
if(node.id=="text:normal"||node.id=="text:newline")
node.removeNode(true);
}
if(this.isConnector(shape)){
var bgShape=shape.getElementsByTagName("rect");
if(bgShape.length>0){
this.hideConnectorBackground(bgShape[0]);
}
}
}
/*a utility function to perform word wrap
* @param m max length of string
* @param b token to use for each break e.g \n or <br>
* @param c boolean indicating if hard break should be forced if string longer than m
* @credits: Jonas Raoni Soares Silva:http://jsfromhell.com/string/wordwrap [v1.0]
**/
String.prototype.wordWrap = function(m, b, c){
var i, j, l, s, r = this.split("\n");
if(m > 0) for(i in r){
for(s = r[i], r[i] = ""; s.length > m;
j = c ? m : (j = s.substr(0, m).match(/\S*$/)).input.length - j[0].length
|| m,
r[i] += s.substr(0, j) + ((s = s.substr(j)).length ? b : "")
);
r[i] += s;
}
return r.join("\n");
};
/**
*utility function to set the fontsize,fontcolor,fontfamily,fontdecoration(bold,italics,underline) and textalign for a given shape
* if you want to selectively set something e.g size, then only pass size in the font leaving the rest of the stuff as null
*/
VMLRenderer.prototype.setFont=function(shape,font,zoom){
var dummyText=this.getShapeText(shape);
//if this is null, then dummy text does not exist
//so we have to create one and then we leave
if(!dummyText){
this.fillUpFont(font);
this.setShapeText(shape," ",font,true,null,zoom);
return;
}
//we already have text...now we can start, get the shapes first
var nodeList=shape.getElementsByTagName("line");
//we will initialize the textpath list later when we need it
var textList=new Array();
if(font.family!=''||font.bold!=''||font.align!=''||font.italics!=''){
for(var i=0;i<nodeList.length;i++){
var textPaths=nodeList[i].getElementsByTagName("textpath");
if(textPaths.length>0){
textList[textList.length]=textPaths[0];
}
}
}
var shapeFont=this.getFont(shape);
//if font size changes, we really need to redo the spacing etc.
if(font.size!=''&&(font.size!=shapeFont.size)){
this.clearShapeText(shape);
this.setShapeText(shape,dummyText,font,true,shapeFont,zoom);
}
//otherwise we will set things individually, no need to create things
if(font.color!=''){
//debugger;
for(var i=0;i<nodeList.length;i++){
if(nodeList[i].id.indexOf("text:")>=0){
nodeList[i].fillcolor=font.color;
nodeList[i].strokecolor=font.color;
}
}
}
//now set the text path specific properties
if(font.family!=''){
//IE 7.0 follows css 2.1 spec closely, so we need to add the ' around the font name
for(var i=0;i<textList.length;i++){
var textItem=textList[i];
textItem.style.fontFamily=font.family;
}
}
if(font.bold!=''){
for(var i=0;i<textList.length;i++){
textList[i].style.fontWeight=font.bold;
}
}
if(font.italics!=''){
for(var i=0;i<textList.length;i++){
textList[i].style.fontStyle=font.italics;
}
}
if(font.align!=''){
//debugger;
var re = new RegExp("\\bv-text-align:(\\s)*[a-z]+\\b", "g");
for(var i=0;i<textList.length;i++){
var textItem=textList[i];
textItem.style.cssText=textList[i].style.cssText.replace(re,"v-text-align:"+font.align);
var parent=textItem.parentElement;
textItem.removeNode(true);
parent.appendChild(textItem);
}
}
}
/**
*this method will pull out the font from the dummyText and then report it back
**/
VMLRenderer.prototype.getFont=function(shape){
var font=new Object();
font.size="16";
font.family="'arial'";
font.color='black';
font.align='center';
font.italics='';
font.bold='';
//for backward compatibility. after 0.2 we will use "text:template";
var element=document.getElementById("text:dummy"+shape.id);;
if(!element){
element=document.getElementById("text:template"+shape.id);
}
if(!element)
return font;
else{
if(element.parentElement.fillcolor)
font.color=element.parentElement.fillcolor.value;
if(element.style.fontFamily)
font.family=element.style.fontFamily;
if(element.style.fontSize)
font.size=element.style.fontSize.split("px")[0];
if(element.style.fontWeight)
font.bold=element.style.fontWeight;
if(element.style.fontStyle)
font.italics=element.style.fontStyle;
//todo for align!!!
if(element.style.cssText){
var cssText=element.style.cssText;
var vAlignIndex=cssText.split("v-text-align:");
if(vAlignIndex.length>1){
var vAlignEnd=vAlignIndex[1].split(";");
if(vAlignEnd.length>0){
font.align=trim(vAlignEnd[0]);
}
}
}
}
return font;
}
/**
*append an attribute to the page cumulate draw specific
**/
VMLRenderer.prototype.appendPageAttribute=function(div,attribute){
if(div)div.appendChild(attribute);
}
/**
*return the real data embedded in the richdraw editor
**/
VMLRenderer.prototype.getRealData=function(){
var div=this.createElement("div");
div.insertAdjacentHTML("AfterBegin",this.container.innerHTML);
var textElements=div.getElementsByTagName("textpath");
for(var i=0;i<textElements.length;i++){
if(textElements[i].string){
var theString=textElements[i].string;
var node=this.container.ownerDocument.createTextNode(theString);
textElements[i].appendChild(node);
textElements[i].string=null;
}
}
return div;
}
/**
*return the response as a valid xml document, since version 0.3.7 we move the strings in the textpath string
* attribute into the node to prevent invalid xml
**/
VMLRenderer.prototype.getValidDocumentFromResponse=function(response){
var div=this.createElement("div");
div.innerHTML=response;
return div;
}
/**
*open the objects in .mmd file
**/
VMLRenderer.prototype.open=function(div){
var nodes=this.getAllShapes(div);
var nodeArray=$A(nodes);
for(var i=0;i<nodeArray.length;i++){
this.container.appendChild(nodeArray[i]);
this.updateZIndex(nodeArray[i]);
}
nodes=this.getAllConnectors(div);
nodeArray=$A(nodes);
for(var i=0;i<nodeArray.length;i++){
var from,to,c1,c2=null;
var subject=this.getShapeSubject(nodeArray[i]);
//wierd IE bug which needs line zindex to be 0 until its added to the container....
//debugger;
var type=this.getConnectorType(nodeArray[i]);
var lookup=(type=='line')?'line':'curve';
if(type=='ortho-line'){
lookup='polyline';
//set points to 0,0 for polylines, before we add them
nodeArray[i].getElementsByTagName(lookup)[0].points="0,0";
}
//hack for curve
if(type=='curve-line'){
from=subject.from;
to= subject.to;
c1=subject.control1;
c2=subject.control2;
subject.from="0,0";
subject.to="10,10";
subject.control1="1,1";
subject.control2="1,1";
}
var zIndex=nodeArray[i].getElementsByTagName(lookup)[0].style.zIndex;
nodeArray[i].getElementsByTagName(lookup)[0].style.zIndex=0;
this.container.appendChild(nodeArray[i]);
//hack for polylines
if(type=='ortho-line'){
var points=nodeArray[i].getAttribute("polyline-path");
nodeArray[i].getElementsByTagName("polyline")[0].points.value=points;
}
//hack for curve
if(type=='curve-line'){
subject.from=from;
subject.to=to;
subject.control1=c1;
subject.control2=c2;
}
nodeArray[i].getElementsByTagName(lookup)[0].style.zIndex=zIndex;
this.updateZIndex(nodeArray[i]);
}
}
/**a utility function to trim strings**/
function trim(TRIM_VALUE){
if(TRIM_VALUE.length < 1){
return"";
}
TRIM_VALUE = RTrim(TRIM_VALUE);
TRIM_VALUE = LTrim(TRIM_VALUE);
if(TRIM_VALUE==""){
return "";
}
else{
return TRIM_VALUE;
}
}
function RTrim(VALUE){
var w_space = String.fromCharCode(32);
var v_length = VALUE.length;
var strTemp = "";
if(v_length < 0){
return"";
}
var iTemp = v_length -1;
while(iTemp > -1){
if(VALUE.charAt(iTemp) == w_space){
}
else{
strTemp = VALUE.substring(0,iTemp +1);
break;
}
iTemp = iTemp-1;
} //End While
return strTemp;
} //End Function
function LTrim(VALUE){
var w_space = String.fromCharCode(32);
if(v_length < 1){
return"";
}
var v_length = VALUE.length;
var strTemp = "";
var iTemp = 0;
while(iTemp < v_length){
if(VALUE.charAt(iTemp) == w_space){
}
else{
strTemp = VALUE.substring(iTemp,v_length);
break;
}
iTemp = iTemp + 1;
} //End While
return strTemp;
} //End Function